﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using SystemDiagramNew.TypeDefinition;
using SystemDiagramNew.Utils;

namespace SystemDiagramNew.SystemDiagramLegend
{
	public class DrawingPlotter
	{
        public DrawingPlotter(System.Windows.Forms.Control control, Graphics graphics, List<CurveInfo> curves, List<TextNoteInfo> textNotes, List<FillRegion> fillRegions)
		{
			this.DrawReferenceBox = false;
			this.m_Control = control;
			this.m_Graphics = graphics;
			this.m_Curves = curves;
			this.m_TextNotes = textNotes;
			this.m_FillRegions = fillRegions;
		}

		public bool DrawReferenceBox { get; set; }

		public void Draw()
		{
			if (this.m_Curves.Count < 1)
			{
				return;
			}
			this.m_Graphics.SmoothingMode = SmoothingMode.HighQuality;
			this.m_Graphics.PixelOffsetMode = PixelOffsetMode.HighSpeed;
            this.m_Graphics.Clear(System.Drawing.Color.White);
			Size size = this.m_Control.Size;
			Size size2 = new Size((int)(0.9 * (double)size.Width), (int)(0.9 * (double)size.Height));
			Transform trans = this.ComputerTransMatrix(size2);
			List<CurveInfo> list = new List<CurveInfo>();
			list.AddRange(this.m_Curves);
			list.AddRange(this.m_ReferenceBox);
			foreach (CurveInfo curveInfo in list)
			{
				Pen penWithCurveInfo = this.GetPenWithCurveInfo(curveInfo.Color, curveInfo.PenDashStyle, curveInfo.LineWidth);
				EdgeInfo curveObj = curveInfo.CurveObj;
				if (Geometry.IsEqual(curveObj.Bulge, 0.0))
				{
					this.DrawLine(penWithCurveInfo, curveObj.StartPoint, curveObj.EndPoint, trans);
				}
				else
				{
					this.DrawArc(penWithCurveInfo, curveObj.StartPoint, curveObj.EndPoint, curveObj.Bulge, trans);
				}
			}
			foreach (TextNoteInfo textNoteInfo in this.m_TextNotes)
			{
				this.DrawText(textNoteInfo, trans);
			}
			foreach (FillRegion fillRegion in this.m_FillRegions)
			{
				this.DrawFillRegion(fillRegion, trans);
			}
		}

		private Pen GetPenWithCurveInfo(PenColor penColor, DashStyle penDashStyle, float lineWidth)
		{
            System.Drawing.Color color = this.PenColorToColor(penColor);
			return new Pen(color, lineWidth)
			{
				DashStyle = penDashStyle
			};
		}

        private System.Drawing.Color PenColorToColor(PenColor penColor)
		{
            System.Drawing.Color white = System.Drawing.Color.White;
			switch (penColor)
			{
			case PenColor.PC_Red:
            return System.Drawing.Color.Red;
			case PenColor.PC_Blue:
            return System.Drawing.Color.Blue;
			case PenColor.PC_Green:
            return System.Drawing.Color.Green;
			case PenColor.PC_Gray:
            return System.Drawing.Color.Gray;
			case PenColor.PC_Yellow:
            return System.Drawing.Color.Yellow;
			case PenColor.PC_Black:
            return System.Drawing.Color.Black;
			}
            return System.Drawing.Color.White;
		}

		private Transform ComputerTransMatrix(Size size)
		{
			Transform identity = Transform.Identity;
			identity.Origin = XYZ.Zero;
			identity.BasisX = XYZ.BasisX;
			identity.BasisY = -XYZ.BasisY;
			identity.BasisZ = XYZ.BasisZ;
			BoundingBoxUV boundingBoxUV = this.GetBoundingBox();
			if (this.DrawReferenceBox && this.m_ReferenceBox.Count == 0)
			{
				double num = boundingBoxUV.Min.U + (boundingBoxUV.Max.U - boundingBoxUV.Min.U) / 2.0;
				double num2 = boundingBoxUV.Min.V + (boundingBoxUV.Max.V - boundingBoxUV.Min.V) / 2.0;
				double num3 = num - this.m_ReferenceBoxWidth / 2.0;
				double num4 = num + this.m_ReferenceBoxWidth / 2.0;
				double num5 = num2 + this.m_ReferenceBoxWidth / 2.0;
				double num6 = num2 - this.m_ReferenceBoxWidth / 2.0;
				XYZ xyz = new XYZ(num3, num6, 0.0);
				XYZ xyz2 = new XYZ(num3, num5, 0.0);
				XYZ xyz3 = new XYZ(num4, num5, 0.0);
				XYZ xyz4 = new XYZ(num4, num6, 0.0);
				float lineWidth = 1f;
				if (this.m_Curves.Count > 0)
				{
					lineWidth = this.m_Curves[0].LineWidth;
				}
				EdgeInfo curve = new EdgeInfo(xyz, xyz4, 0.0);
				CurveInfo item = new CurveInfo(curve, PenColor.PC_Gray, DashStyle.Dash, lineWidth);
				this.m_ReferenceBox.Add(item);
				EdgeInfo curve2 = new EdgeInfo(xyz4, xyz3, 0.0);
				CurveInfo item2 = new CurveInfo(curve2, PenColor.PC_Gray, DashStyle.Dash, lineWidth);
				this.m_ReferenceBox.Add(item2);
				EdgeInfo curve3 = new EdgeInfo(xyz3, xyz2, 0.0);
				CurveInfo item3 = new CurveInfo(curve3, PenColor.PC_Gray, DashStyle.Dash, lineWidth);
				this.m_ReferenceBox.Add(item3);
				EdgeInfo curve4 = new EdgeInfo(xyz2, xyz, 0.0);
				CurveInfo item4 = new CurveInfo(curve4, PenColor.PC_Gray, DashStyle.Dash, lineWidth);
				this.m_ReferenceBox.Add(item4);
				BoundingBoxUV box = Geometry.CalculateBoundingBox2D(xyz, xyz4);
				boundingBoxUV = Geometry.BoundingBoxesMerge(boundingBoxUV, box);
				box = Geometry.CalculateBoundingBox2D(xyz3, xyz2);
				boundingBoxUV = Geometry.BoundingBoxesMerge(boundingBoxUV, box);
			}
			UV max = boundingBoxUV.Max;
			UV min = boundingBoxUV.Min;
			double num7 = (double)size.Width / (max.U - min.U);
			double num8 = (double)size.Height / (max.V - min.V);
			double num9 = (num7 <= num8) ? num7 : num8;
			Transform transform = Transform.Identity;
			transform = transform.ScaleBasis(num9);
			XYZ vector = new XYZ((min.U + max.U) / 2.0, (min.V + max.V) / 2.0, 0.0);
			Transform transform2 = RevitVersionFuncs.CreateTranslation(vector);
			Transform transform3 = Transform.Identity;
			transform3 = transform3.Multiply(identity.Inverse);
			transform3 = transform3.Multiply(transform);
			return transform3.Multiply(transform2.Inverse);
		}

		public BoundingBoxUV GetBoundingBox()
		{
			BoundingBoxUV boundingBoxUV = null;
			List<EdgeInfo> list = new List<EdgeInfo>();
			foreach (CurveInfo curveInfo in this.m_Curves)
			{
				EdgeInfo curveObj = curveInfo.CurveObj;
				list.Add(curveObj);
			}
			foreach (FillRegion fillRegion in this.m_FillRegions)
			{
				list.AddRange(fillRegion.EdgeLoop);
			}
			foreach (EdgeInfo edgeInfo in list)
			{
				if (Geometry.IsEqual(edgeInfo.Bulge, 0.0))
				{
					if (boundingBoxUV == null)
					{
						boundingBoxUV = Geometry.CalculateBoundingBox2D(edgeInfo.StartPoint, edgeInfo.EndPoint);
					}
					else
					{
						BoundingBoxUV box = Geometry.CalculateBoundingBox2D(edgeInfo.StartPoint, edgeInfo.EndPoint);
						boundingBoxUV = Geometry.BoundingBoxesMerge(boundingBoxUV, box);
					}
				}
				else
				{
					XYZ startPoint = edgeInfo.StartPoint;
					XYZ endPoint = edgeInfo.EndPoint;
					XYZ ptCenter = null;
					XYZ normal = XYZ.BasisZ;
					double radius = 0.0;
					double num = 0.0;
					double num2 = 0.0;
					Geometry.GetArcInfoWithBulge(startPoint, endPoint, edgeInfo.Bulge, ref ptCenter, ref radius, ref num, ref num2);
					if (Geometry.LessThan(edgeInfo.Bulge, 0.0))
					{
						normal = -XYZ.BasisZ;
					}
					if (boundingBoxUV == null)
					{
						boundingBoxUV = Geometry.CalculateBoundingBox2D(startPoint, endPoint, ptCenter, normal, radius);
					}
					else
					{
						BoundingBoxUV box2 = Geometry.CalculateBoundingBox2D(startPoint, endPoint, ptCenter, normal, radius);
						boundingBoxUV = Geometry.BoundingBoxesMerge(boundingBoxUV, box2);
					}
				}
			}
			return boundingBoxUV;
		}

		private void DrawLine(Pen pen, XYZ ptS, XYZ ptE, Transform trans)
		{
			ptS = Geometry.TransformPoint(ptS, trans);
			ptE = Geometry.TransformPoint(ptE, trans);
			PointF pt = new PointF((float)ptS.X, (float)ptS.Y);
			PointF pt2 = new PointF((float)ptE.X, (float)ptE.Y);
			this.m_Graphics.DrawLine(pen, pt, pt2);
		}

		private void DrawArc(Pen pen, XYZ ptS, XYZ ptE, double bugle, Transform trans)
		{
			XYZ xyz = null;
			double num = 0.0;
			double num2 = 0.0;
			double num3 = 0.0;
			Geometry.GetArcInfoWithBulge(ptS, ptE, bugle, ref xyz, ref num, ref num2, ref num3);
			float num4 = (float)(num * trans.Scale);
			XYZ basisZ = XYZ.BasisZ;
			if (Geometry.LessThan(bugle, 0.0))
			{
                //-XYZ.BasisZ;
			}
			float num5 = 6.28318548f - (float)num3;
			float num6 = 6.28318548f - (float)num2;
			if (num5 > num6)
			{
				num6 += 6.28318548f;
			}
			float num7 = num6 - num5;
			num5 = num5 * 180f / 3.14159274f;
			num7 = num7 * 180f / 3.14159274f;
			xyz = Geometry.TransformPoint(xyz, trans);
			float x = (float)(xyz.X - (double)num4);
			float y = (float)(xyz.Y - (double)num4);
			float num8 = num4 * 2f;
			this.m_Graphics.DrawArc(pen, x, y, num8, num8, num5, num7);
		}

		private void DrawText(TextNoteInfo textNoteInfo, Transform trans)
		{
			if (textNoteInfo.m_Text.CompareTo("") == 0)
			{
				return;
			}
			float emSize = (float)(textNoteInfo.m_Height * trans.Scale * 0.3528 * 0.5);
			Font font = new Font("宋体", emSize);
            System.Drawing.Color color = this.PenColorToColor(textNoteInfo.m_Color);
			SolidBrush brush = new SolidBrush(color);
			XYZ xyz = Geometry.TransformPoint(textNoteInfo.m_Center, trans);
			double num = textNoteInfo.m_BoundingBoxWidth.MMtoFeet() * trans.Scale;
			double num2 = textNoteInfo.m_BoundingBoxHeight.MMtoFeet() * trans.Scale;
			double num3 = xyz.X - num / 2.0;
			double num4 = xyz.Y - num2 / 2.0;
			Rectangle rectangle = new Rectangle((int)num3, (int)num4, (int)num, (int)num2);
			StringFormat stringFormat = new StringFormat();
			stringFormat.LineAlignment = StringAlignment.Center;
			stringFormat.Alignment = StringAlignment.Center;
			this.m_Graphics.FillEllipse(Brushes.White, rectangle);
			this.m_Graphics.DrawString(textNoteInfo.m_Text, font, brush, rectangle, stringFormat);
		}

		private void DrawFillRegion(FillRegion fillRegion, Transform trans)
		{
			try
			{
				List<EdgeInfo> edgeLoop = fillRegion.EdgeLoop;
				List<XYZ> list = new List<XYZ>();
				List<double> list2 = new List<double>();
				double num = 0.0;
				for (int i = 0; i < edgeLoop.Count; i++)
				{
					EdgeInfo edgeInfo = edgeLoop[i];
					num += edgeInfo.Length();
					list.Add(edgeInfo.StartPoint);
					list2.Add(edgeInfo.Bulge);
				}
				double fitSpace = num / (double)edgeLoop.Count / 10.0;
				List<XYZ> list3 = new List<XYZ>();
				Geometry.GetFittingPolyline(list, list2, ref list3, fitSpace);
				for (int i = 0; i < list3.Count; i++)
				{
					list3[i] = Geometry.TransformPoint(list3[i], trans);
				}
				GraphicsPath graphicsPath = new GraphicsPath();
				for (int i = 0; i < list3.Count; i++)
				{
					XYZ xyz = list3[i];
					XYZ xyz2;
					if (i == list3.Count - 1)
					{
						xyz2 = list3[0];
					}
					else
					{
						xyz2 = list3[i + 1];
					}
					graphicsPath.AddLine((float)xyz.X, (float)xyz.Y, (float)xyz2.X, (float)xyz2.Y);
				}
				this.m_Graphics.FillRegion(Brushes.Black, new Region(graphicsPath));
			}
			catch (Exception)
			{
			}
		}

        private readonly System.Windows.Forms.Control m_Control;

		private readonly List<CurveInfo> m_Curves = new List<CurveInfo>();

		private readonly List<FillRegion> m_FillRegions = new List<FillRegion>();

		private readonly Graphics m_Graphics;

		private readonly List<CurveInfo> m_ReferenceBox = new List<CurveInfo>();

		private readonly double m_ReferenceBoxWidth = 6.0;

		private readonly List<TextNoteInfo> m_TextNotes = new List<TextNoteInfo>();
	}
}
